﻿/*========================== 
 * @author 郑金泉
 * @desc 方法响应类
 * ========================= */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.IO;

using Obsidian.Edm;

namespace Obsidian.Action
{
    public class ActionResponse
    {
	    public const int STATUS_OK = 1;
        public const int STATUS_ERROR = 0;

        private int _statusCode = 1;
        private string _message = "";
        private ActReqHandler actReqHandler;
        private List<ActionResult> _listResults = new List<ActionResult>();
        private Dictionary<string, ActionResult> _dictResults = new Dictionary<string, ActionResult>();

        public int StatusCode
        {
            get { return this._statusCode; }
            set { this._statusCode = value; }
        }

        public string Message
        {
            get { return this._message; }
            set 
            {
                if (value == null)
                    this._message = "";
                else
                    this._message = value; 
            }
        }

        public List<ActionResult> Results
        {
            get { return this._listResults; }
        }

        public bool HasResults
        {
            get { return this._listResults.Count > 0;}
        }

        public ActionResult FirstResult
        {
            get { return this._listResults[0]; }
        }

        internal ActionResponse(ActReqHandler arh) 
        {
            this.actReqHandler = arh;
        }

        public ActionResult AddResult(string name, string fileds)
        {
            ActionResult rs = new ActionResult(name, fileds);
            this.AddResult(rs);
            return rs;
        }

        public ActionResult AddResult(string name, string fileds, IModel model)
        {
            ActionResult rs = this.AddResult(name, fileds);
            rs.AddModel(model);
            return rs;
        }

        public ActionResult AddResult(string name, string fileds, string idField, IModel model)
        {
            ActionResult rs = this.AddResult(name, fileds);
            rs.AddModel(model);
            return rs;
        }

        public ActionResult AddResult(string name, string fileds, string idField, string modelPath, IModel model)
        {
            ActionResult rs = new ActionResult(name, fileds, idField, modelPath);
            rs.AddModel(model);
            this.AddResult(rs);
            return rs;
        }

        public ActionResult AddResult<T>(string name, string fileds, IEnumerable<T> models) where T : IModel, new()
        {
            ActionResult rs = this.AddResult(name, fileds);
            rs.AddModels(models);
            return rs;
        }

        public ActionResult AddResult<T>(string name, string fileds, string idField, IEnumerable<T> models) where T : IModel, new()
        {
            ActionResult rs = new ActionResult(name, fileds, idField);
            rs.AddModels(models);
            this.AddResult(rs);
            return rs;
        }

        public ActionResult AddResult<T>(string name, string fileds, string idField, string modelPath, IEnumerable<T> models) where T : IModel, new()
        {
            ActionResult rs = new ActionResult(name, fileds, idField, modelPath);
            rs.AddModels(models);
            this.AddResult(rs);
            return rs;
        }

        internal void AddResult(ActionResult result)
        {
            this._listResults.Add(result);
            string name = result.Name;
            if (!String.IsNullOrEmpty(name))
                this._dictResults.Add(name, result);
        }

        public int ResultCount
        {
            get { return this._listResults.Count; }
        }

        public bool HasResult(string name)
        {
            return this._dictResults.ContainsKey(name);
        }

        public ActionResult GetResult(int index)
        {
            return this._listResults[index];
        }

        public ActionResult GetResult(string name)
        {
            ActionResult rs;
            if (this._dictResults.TryGetValue(name, out rs))
                return rs;
            else
                return null;
        }

        public void Error()
        {
            this.Error("");
        }

        public void Error(string msg)
        {
            this._statusCode = STATUS_ERROR;
            this.Message = msg;
        }

        public void SessionInvalid()
        {
            this.actReqHandler.SessionInvalid();
        }

        internal void WriterOutputForCompress(JsonWriter jw)
        {
            jw.WriteStartObject();
            jw.WritePropertyName("s");
            jw.WriteValue(this.StatusCode);
            jw.WritePropertyName("m");
            jw.WriteValue(this.Message);
            jw.WritePropertyName("r");
            jw.WriteStartArray();
            foreach (ActionResult ar in this.Results)
                ar.WriterOutputForCompress(jw);
            jw.WriteEndArray();
            jw.WriteEndObject();
        }

        internal void ReadInput(JsonReader jr)
        {
            string propName;
            while (jr.Read())
            {
                if (jr.TokenType == JsonToken.EndObject)
                    break;

                if (jr.TokenType == JsonToken.PropertyName)
                {
                    propName = Convert.ToString(jr.Value);
                    jr.Read();
                    if (propName == "s")
                    {
                        this._statusCode = Convert.ToInt32(jr.Value);
                    }
                    else if (propName == "m")
                    {
                        this._message = Convert.ToString(jr.Value);
                    }
                    else if (propName == "r")
                    {
                        this.ReadResults(jr);
                    }
                }
            }
        }

        internal void ReadResults(JsonReader jr)
        {
            string propName;
            string rsName = "";
            string fields = "";
            ActionResult result;
            while(jr.Read())
            {
                if (jr.TokenType == JsonToken.EndArray)
                    break;

                while (jr.Read())
                {
                    if (jr.TokenType == JsonToken.EndObject)
                        break;

                    if (jr.TokenType == JsonToken.PropertyName)
                    {
                        propName = Convert.ToString(jr.Value);
                        jr.Read();
                        if (propName == "n")
                        {
                            rsName = Convert.ToString(jr.Value);
                        }
                        else if (propName == "f")
                        {
                            fields = Convert.ToString(jr.Value);
                        }
                        else if (propName == "v")
                        {
                            string[] arrFiels = fields.Split(',');
                            result = new ActionResult(rsName, arrFiels);
                            this._listResults.Add(result);
                            if (!String.IsNullOrEmpty(rsName))
                                this._dictResults.Add(rsName, result);

                            while (jr.Read())
                            {
                                if (jr.TokenType == JsonToken.EndArray)
                                    break;
                                if (jr.TokenType == JsonToken.StartArray)
                                {
                                    object[] arrObj = new object[arrFiels.Length];
                                    int i = 0;
                                    while (jr.Read())
                                    {
                                        if (jr.TokenType == JsonToken.EndArray)
                                        {
                                            result.AddValues(arrObj);
                                            break;
                                        }
                                        arrObj[i] = jr.Value;
                                        i++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


    }
}
